package com.luxiu.extensionlib.cardView

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.RelativeLayout
import androidx.core.content.ContextCompat
import com.luxiu.extensionlib.R


class HarclsibleCardLayout(
    context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0,
) : RelativeLayout(context, attrs, defStyleAttr, defStyleRes) {

    private var mTopTabView: ViewGroup? = null
    private var mContentView: ViewGroup? = null
    private var isExpanded: Boolean = false
    private var mCollapsible = true
    private var mAnimationDuration = 300
    private var mContentViewHeight = 0
    private var mListener: OnItemStateChanged? = null

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)

    init {
        val ta = context!!.obtainStyledAttributes(attrs, R.styleable.HarclsibleCardLayout, defStyleAttr, defStyleRes)
        try {
            // 保存属性数据以便后续使用，可用于恢复视图状态等操作
            saveAttributeDataForStyleable(context, R.styleable.HarclsibleCardLayout, attrs, ta , defStyleAttr, defStyleRes)

            // 获取颜色资源 ID，如果未指定则使用默认的白色
            val colorRes = ta.getResourceId(R.styleable.HarclsibleCardLayout_mColorRes, R.color.white)
            // 获取卡片圆角半径，如果未指定则默认为 0f
            val cardCornerRadius = ta.getDimension(R.styleable.HarclsibleCardLayout_mCardCornerRadius, 0f)
            // 获取卡片的阴影高度，如果未指定则默认为 0f
            val elevationFloat = ta.getDimension(R.styleable.HarclsibleCardLayout_mElevation, 0f)

            // 创建一个 GradientDrawable 作为背景
            val drawable = GradientDrawable().apply {
                shape = GradientDrawable.RECTANGLE
                setColor(ContextCompat.getColor(context, colorRes))
                cornerRadius = cardCornerRadius
            }
            background = drawable
            clipToOutline = true
            elevation = elevationFloat
        } finally {
            ta.recycle()
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        initChildView()
    }

    private fun initChildView() {
        if (childCount <= 0) {
            throw RuntimeException("需要一个顶部标题View 也就是当View折叠时出现的View" + "Please set sub_item_layout value")
        }
        mTopTabView = getChildAt(0) as ViewGroup
        mContentView = getChildAt(1) as ViewGroup

        if (mContentView == null) {
            mCollapsible = false
        } else {
            mContentView!!.post {
                if (mContentViewHeight <= 0) {
                    mContentViewHeight = mContentView!!.measuredHeight
                }
            }
            //Animate sub view in
            if (isExpanded) {
                setViewHeight(mContentView!!, 0)
                expandSubItemsWithAnimation(mContentViewHeight.toFloat())
                animateSubItemAppearance(mContentView!!, true)
            }
        }
        if (mCollapsible) {
            mTopTabView!!.setOnClickListener { toggleExpanded() }
            collapse()
        } else {
            isExpanded = true
        }
    }


    fun setStateChangedListener(listener: OnItemStateChanged?) {
        mListener = listener
    }

    private fun collapse() {
        isExpanded = false
        mContentView!!.post { setViewHeight(mContentView!!, 0) }
    }

    private fun toggleExpanded() {
        //modify 24.4.10 如果是recyclerView，getChildCount是0
        if (mContentView == null /*||mContentView.getChildCount() == 0*/) {
            return
        }
        isExpanded = !isExpanded
        if (mListener != null) {
            mListener!!.itemCollapseStateChanged(isExpanded)
        }
        val currentContentViewHeight = mContentView!!.measuredHeight.toFloat()
        //modify start 24.4.9 添加收回动画 如果mIsContentShown为true，则从0开始动画，否则从当前高度开始
        expandSubItemsWithAnimation(if (isExpanded) 0f else currentContentViewHeight)
        //        expandSubItemsWithAnimation(0f);
        //modify end
        animateViewAlpha(mContentView)
    }

    private fun animateViewAlpha(viewGroup: ViewGroup?) {
        if (viewGroup == null) {
            return
        }

        val animation =
            if (isExpanded) ValueAnimator.ofFloat(0f, 1f) else ValueAnimator.ofFloat(1f, 0f)
        animation.setDuration(if (isExpanded) mAnimationDuration * 2L else mAnimationDuration.toLong())

        animation.addUpdateListener { anim ->
            val value = anim.animatedValue as Float
            viewGroup.alpha = value
        }
        animation.start()
    }

    /**
     * 在内容展开时，根据动画动态设置高度
     */
    private fun expandSubItemsWithAnimation(startingPos: Float) {
        val animation = if (isExpanded) ValueAnimator.ofFloat(
            startingPos,
            mContentViewHeight.toFloat()
        ) else  //modify start 24.4.9 添加收回动画 如果mIsContentShown为false，则从当前高度开始动画
            ValueAnimator.ofFloat(startingPos, 0f)
        //                ValueAnimator.ofFloat(mContentViewHeight, startingPos);
        ////modify end
        animation.interpolator = AccelerateDecelerateInterpolator()
        animation.setDuration(mAnimationDuration.toLong())

        animation.addUpdateListener { anim ->
            val value = anim.animatedValue as Float
            setViewHeight(mContentView!!, value.toInt())
        }
        animation.start()
    }

    private fun animateSubItemAppearance(contentView: View, isAdding: Boolean) {
        val alphaAnimation =
            if (isAdding) ValueAnimator.ofFloat(0f, 1f) else ValueAnimator.ofFloat(1f, 0f)
        alphaAnimation.setDuration(if (isAdding) mAnimationDuration * 2L else (mAnimationDuration / 2).toLong())

        val heightAnimation = if (isAdding) ValueAnimator.ofFloat(
            0f,
            mContentViewHeight.toFloat()
        ) else ValueAnimator.ofFloat(mContentViewHeight.toFloat(), 0f)
        heightAnimation.setDuration((mAnimationDuration / 2).toLong())
        heightAnimation.startDelay = (mAnimationDuration / 2).toLong()

        alphaAnimation.addUpdateListener { animation ->
            val `val` = animation.animatedValue as Float
            contentView.alpha = `val`
        }
        alphaAnimation.start()
        heightAnimation.start()
    }

    private fun setViewHeight(v: View, height: Int) {
        val params = v.layoutParams
        params.height = height
        v.requestLayout()
    }

    interface OnItemStateChanged {
        fun itemCollapseStateChanged(expanded: Boolean)
    }

}